/*
 * Copyright (c) 2015 LingoChamp Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.tools.cleanmaster.functionpage;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;

import com.tools.cleanmaster.R;

import java.lang.ref.WeakReference;


/**
 * Created by Jacksgong on 12/8/15.
 */
public class MemoryProgressCircle extends View implements ISmoothTarget {

    // ColorInt
    private int startColor;
    // ColorInt
    private int endColor;
    // ColorInt
    private int middleColor;
    // max circle colorInt
    private int maxCircleColor;
    // inner circle colorInt
    private int innerCircleColor;


    private int percentEndColor;

    private int strokeWidth;
    private int maxCircleWidth;
    private int innerCircleWidth;
    private float percent;

    // 用于渐变
    private Paint paint;
    // 大圆
    private Paint maxCirclePaint;
    // 内圆
    private Paint innerCirclePaint;

    //三个圆环的半径
    private int radius = 200;

    private SmoothHandler smoothHandler;
    private RectF oval;

    public MemoryProgressCircle(Context context) {
        super(context);
        init(context, null);
    }

    public MemoryProgressCircle(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public MemoryProgressCircle(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(final Context context, final AttributeSet attrs) {
        float defaultPercent = -1;
        if (isInEditMode()) {
            defaultPercent = 0.6f;
        }

        do {
            final int strokeWdithDefaultValue = (int) (18 * getResources().getDisplayMetrics().density + 0.5f);
            if (context == null || attrs == null) {
                strokeWidth = strokeWdithDefaultValue;
                percent = defaultPercent;
                startColor = getResources().getColor(R.color.mpc_start_color);
                endColor = getResources().getColor(R.color.mpc_end_color);
                maxCircleWidth = (int) (28 * getResources().getDisplayMetrics().density + 0.5f);
                innerCircleColor = (int) (10 * getResources().getDisplayMetrics().density + 0.5f);
                break;
            }

            TypedArray typedArray = null;
            try {
                typedArray = context.obtainStyledAttributes(attrs, R.styleable.MemoryProgressCircle);
                percent = typedArray.getFloat(R.styleable.MemoryProgressCircle_mpc_percent, defaultPercent);
                strokeWidth = (int) typedArray.getDimension(R.styleable.MemoryProgressCircle_mpc_stroke_width, strokeWdithDefaultValue);
                startColor = typedArray.getColor(R.styleable.MemoryProgressCircle_mpc_start_color, getResources().getColor(R.color.mpc_start_color));
                endColor = typedArray.getColor(R.styleable.MemoryProgressCircle_mpc_end_color, getResources().getColor(R.color.mpc_end_color));
                middleColor = typedArray.getColor(R.styleable.MemoryProgressCircle_mpc_middle_color, getResources().getColor(R.color.mpc_end_color));

                maxCircleWidth = (int) typedArray.getDimension(R.styleable.MemoryProgressCircle_max_stroke_width, 28);
                innerCircleWidth = (int) typedArray.getDimension(R.styleable.MemoryProgressCircle_inner_stroke_width, 10);
                maxCircleColor = typedArray.getColor(R.styleable.MemoryProgressCircle_max_circle_color, getResources().getColor(R.color.mpc_end_color));
                innerCircleColor = typedArray.getColor(R.styleable.MemoryProgressCircle_inner_circle_color
                        , getResources().getColor(R.color.mpc_end_color));

            } finally {
                if (typedArray != null) {
                    typedArray.recycle();
                }
            }


        } while (false);

        oval = new RectF();

        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(strokeWidth);
        paint.setDither(true);
        paint.setStrokeCap(Paint.Cap.ROUND);


        maxCirclePaint = new Paint();
        maxCirclePaint.setAntiAlias(true);
        maxCirclePaint.setStrokeWidth(maxCircleWidth);
        maxCirclePaint.setStyle(Paint.Style.STROKE);
        maxCirclePaint.setColor(maxCircleColor);

        innerCirclePaint = new Paint();
        innerCirclePaint.setAntiAlias(true);
        innerCirclePaint.setStrokeWidth(innerCircleWidth);
        innerCirclePaint.setStyle(Paint.Style.STROKE);
        innerCirclePaint.setColor(innerCircleColor);

        refreshDelta();
        customColors = new int[]{startColor, middleColor, endColor};
        fullColors = new int[]{startColor, endColor};

        customPositions = new float[3];
        customPositions[0] = 0;
        customPositions[2] = 1;

        extremePositions = new float[]{0, 1};
    }

    private void refreshDelta() {
        int endR = (endColor & 0xFF0000) >> 16;
        int endG = (endColor & 0xFF00) >> 8;
        int endB = (endColor & 0xFF);

        this.startR = (startColor & 0xFF0000) >> 16;
        this.startG = (startColor & 0xFF00) >> 8;
        this.startB = (startColor & 0xFF);

        deltaR = endR - startR;
        deltaG = endG - startG;
        deltaB = endB - startB;
    }

    /**
     * @param percent FloatRange(from = 0.0, to = 1.0)
     */
    public void setPercent(float percent) {
        percent = Math.min(1, percent);
        percent = Math.max(0, percent);

        if (smoothHandler != null) {
            smoothHandler.commitPercent(percent);
        }

        if (this.percent != percent) {
            this.percent = percent;
            invalidate();
        }

    }

    @Override
    public void setSmoothPercent(float percent) {
        getSmoothHandler().loopSmooth(percent);
    }

    @Override
    public void setSmoothPercent(float percent, long durationMillis) {
        getSmoothHandler().loopSmooth(percent, durationMillis);
    }

    private SmoothHandler getSmoothHandler() {
        if (smoothHandler == null) {
            smoothHandler = new SmoothHandler(new WeakReference<ISmoothTarget>(this));
        }
        return smoothHandler;
    }

    public float getPercent() {
        return this.percent;
    }

    private int deltaR, deltaB, deltaG;
    private int startR, startB, startG;

    private void calculatePercentEndColor(final float percent) {
        percentEndColor = ((int) (deltaR * percent + startR) << 16) +
                ((int) (deltaG * percent + startG) << 8) +
                ((int) (deltaB * percent + startB)) + 0xFF000000;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private int[] customColors;
    private int[] fullColors;
    private float[] customPositions;
    private float[] extremePositions;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        radius = getWidth() / 2 - maxCircleWidth / 2;
        final int restore = canvas.save();

        final int cx = getWidth() / 2;
        final int cy = getWidth() / 2;
        onDrawMaxCircle(cx, cy, canvas);
        onDrawInnerCircle(cx, cy, canvas);
        float drawPercent = percent;
        if (drawPercent > 0.97 && drawPercent < 1) {
            drawPercent = 0.97f;
        }

        // 画渐变圆
        canvas.save();
        canvas.rotate(-90, cx, cy);
        int[] colors;
        float[] positions;
        if (drawPercent < 1 && drawPercent > 0) {
            customPositions[1] = drawPercent / 2;
            colors = customColors;
            positions = customPositions;
        } else {
            colors = fullColors;
            positions = extremePositions;
        }

        final SweepGradient sweepGradient = new SweepGradient(getMeasuredWidth() / 2, getMeasuredHeight() / 2, colors, positions);
        paint.setShader(sweepGradient);

        // 确定圆弧的绘制位置，也就是里面圆弧坐标和外面圆弧坐标
        oval.set(getMeasuredWidth() / 2 - radius, getMeasuredHeight() / 2 - radius, getMeasuredWidth()
                / 2 + radius, getMeasuredHeight() / 2 + radius);

        canvas.drawArc(oval, 5, drawPercent * 360, false, paint);

        canvas.restore();
        canvas.restoreToCount(restore);
    }

    private void onDrawMaxCircle(int x, int y, Canvas canvas) {
        canvas.drawCircle(x, y, radius, maxCirclePaint);
    }

    private void onDrawInnerCircle(int x, int y, Canvas canvas) {
        canvas.drawCircle(x, y, radius, innerCirclePaint);
    }
}
